package com.hjh.netty.elect.demo5.codec;

import com.hjh.netty.elect.demo3.CharacterConvert;
import com.hjh.netty.elect.demo5.bean.Pmc350DevPackage;
import com.hjh.netty.elect.demo5.constants.Pmc350DevConstant;
import com.hjh.netty.elect.demo5.parser.impl.AutoSendTool;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public class Pmc350DevDecoder extends ByteToMessageDecoder {

    private static final int HEADER_SIZE = 7;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        String dataPackage = ByteBufUtil.hexDump(in);
        log.info("decode|dataPackage:{}",dataPackage);
        //可读的字节数
        int length = in.readableBytes();
        log.info("decode|length:{}",length);
        //最小7个节点
        if (length < Pmc350DevConstant.PACKAGE_MIN_SIZE) {
            log.info("decode|minSize|length<7|len:{}", length);
            return;
        }
        //固定（F9）开头
        //第一个字节，headerBeginMark
        String headerBeginMark = ByteBufUtil.hexDump(new byte[]{in.readByte()}).toUpperCase();
        if (!Pmc350DevConstant.PACKAGE_BEGIN_MARK.equals(headerBeginMark)) {
            log.info("decode|headerBeginMark| is not F9|packetHeader:{}|len:{}", headerBeginMark, length);
            return;
        }

        //第2个字节：包标识，packageType
        int packageType = CharacterConvert.byteToInt(in.readByte());

        //第3个字节：设备识别码长度，devSnLen
        //0标识长度为1；
        //1标识长度为2；
        //2标识长度为3；
        //3标识长度为4；
        //4标识长度为5；
        //....
        //15标识长度为16；
        int devSnLen = CharacterConvert.byteToInt(in.readByte());

        //可读的字节小于
        // （设备识别码长度(devSnLen)+PayLoad 部分总长度（1个字节）
        //  +PayLoad 校验和（1个字节）+0xF9(固定)（1个字节））
        if (in.readableBytes() < devSnLen+1 + 3) {
            log.info("decode|devSn|in.readableBytes：{} <len:{}", in.readableBytes(), devSnLen + 3);
            return;
        }

        //设备识别码(注册包) N 字节 N = RegLen，RegLen∈[1，16]
        String devSn = changeToStr(in, devSnLen+1);

        //PayLoad 部分总长度 1 字节 PayLoadLen，PayLoad 的长度 ∈[0,255]
        int payLoadLen = CharacterConvert.byteToInt(in.readByte());

        //PayLoad 校验和 1 字节 PayLoad 部分校验累加和
        int payLoadCheck = CharacterConvert.byteToInt(in.readByte());

        //0xF9(固定) 1 字
        String headerEndMark = ByteBufUtil.hexDump(new byte[]{in.readByte()}).toUpperCase();
        if (in.readableBytes() != payLoadLen) {
            log.info("decode|payLoad|in.readableBytes：{} != payLoadLen:{}", in.readableBytes(), payLoadLen);
            return;
        }

//        ByteBuf payLoad = in.readBytes(in.readableBytes());
        byte[] payLoad = new byte[payLoadLen];
        in.readBytes(payLoad);

        Pmc350DevPackage pmc350DevPackage = Pmc350DevPackage.builder()
                .headerBeginMark(headerBeginMark)
                .packageType(packageType)
                .devSnLen(devSnLen)
                .devSn(devSn)
                .payLoadLen(payLoadLen)
                .payLoadCheck(payLoadCheck)
                .headerEndMark(headerEndMark)
                .payLoad(payLoad).build();

        log.info("decode|pmc350DevPackage:{}", pmc350DevPackage);
        out.add(pmc350DevPackage);
    }


    /**
     * 把devSnLen长度的字节转换位16进制的字符串
     *
     * @param in
     * @param length
     * @return
     */
    private String changeToStr(ByteBuf in, int length) {
        return AutoSendTool.changeToStr(in,length);
    }
}
